﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CloudManager
{
    internal class CloudService
    {

        //Information based on this document: http://www.microsoft.com/en-us/download/details.aspx?id=35474


        private const string ServicesManagerCachePath = @"Software\Microsoft\Office\{0}\Common\ServicesManagerCache";

        public CloudService()
        {
            Guid = System.Guid.NewGuid().ToString("D");
        }

        public CloudService(string guid)
        {
            Guid = guid;
        }

        public const string BaseKey = @"Software\Microsoft\Office\Common\Cloud Storage";

        /// <summary>
        /// The Guid of the CloudService which is used as the name of the key.
        /// </summary>
        /// <remarks>The Guid must be unique for this service</remarks>
        public string Guid { get; set; }

        //Key: DisplayName
        public string DisplayName { get; set; }

        //Key: Description, opt
        public string Description { get; set; }

        //Key: LearnMoreURL
        public string InformationUrl { get; set; }

        //Key: ManageURL, opt
        public string AccountUrl { get; set; }

        //Key: Thumbnails\Url48x48
        public string Url48x48 { get; set; }

        //Key: Thumbnails\Url40x40, opt
        public string Url40x40 { get; set; }

        //Key: Thumbnails\Url32x32, opt
        public string Url32x32 { get; set; }

        //Key: Thumbnails\Url24x24, opt
        public string Url24x24 { get; set; }

        //Key: Thumbnails\Url20x20, opt
        public string Url20x20 { get; set; }

        //Key: Thumbnails\Url16x16, opt
        public string Url16x16 { get; set; }

        //Key: LocalFolderRoot
        public string LocalFolder { get; set; }

        /// <summary>
        /// Save this Cloud Provider
        /// </summary>
        public void Save()
        {
            //Class is imported from MicroSE Framework
            var re = new RegistryEditor();
            var key = BaseKey + @"\" + Guid;
            var thumbnailKey = key + @"\Thumbnails";

            if (string.IsNullOrWhiteSpace(DisplayName) ||
                string.IsNullOrWhiteSpace(InformationUrl) ||
                string.IsNullOrWhiteSpace(Url48x48) ||
                string.IsNullOrWhiteSpace(LocalFolder))
                throw new Exception("Not all required fields completed");

            Action<string, string> sk = (string n, string v) => re.SaveKey(key, n, v);
            Action<string, string> skThumbnail = (string n, string v) => re.SaveKey(thumbnailKey, n, v);

            sk("DisplayName", DisplayName);
            sk("Description", Description);
            sk("LearnMoreURL", InformationUrl);
            sk("ManageURL", AccountUrl);
            sk("LocalFolderRoot", LocalFolder);
            skThumbnail("Url48x48", Url48x48);
            skThumbnail("Url40x40", Url40x40);
            skThumbnail("Url32x32", Url32x32);
            skThumbnail("Url24x24", Url24x24);
            skThumbnail("Url20x20", Url20x20);
            skThumbnail("Url16x16", Url16x16);
        }

        public static CloudService FromRegistery(string guid)
        {
            if (string.IsNullOrWhiteSpace(guid))
                throw new ArgumentException("Parameter not supplied", "guid");

            var cs = new CloudService(guid);
            var re = new RegistryEditor();

            var key = BaseKey + @"\" + cs.Guid;
            var thumbnailKey = key + @"\Thumbnails";

            Func<string, string> gk = (string n) => re.GetSetting(key, n);
            Func<string, string> gkThumbnail = (string n) => re.GetSetting(thumbnailKey, n);

            cs.DisplayName = gk("DisplayName");
            cs.Description = gk("Description");
            cs.InformationUrl = gk("LearnMoreURL");
            cs.AccountUrl = gk("ManageURL");
            cs.Url16x16 = gkThumbnail("Url16x16");
            cs.Url20x20 = gkThumbnail("Url20x20");
            cs.Url24x24 = gkThumbnail("Url24x24");
            cs.Url32x32 = gkThumbnail("Url32x32");
            cs.Url40x40 = gkThumbnail("Url40x40");
            cs.Url48x48 = gkThumbnail("Url48x48");
            cs.LocalFolder = gk("LocalFolderRoot");

            return cs;
        }

        public static IEnumerable<CloudService> GetServices()
        {
            var re = new RegistryEditor();

            var keyObj = re.GetKey(BaseKey, false);

            if (keyObj == null)
                return null;

            var subKeys = keyObj.GetSubKeyNames();
            var services = new List<CloudService>();

            foreach (var sk in subKeys)
            {
                services.Add(FromRegistery(sk));
            }

            return services;
        }

        public void Remove()
        {
            if (string.IsNullOrWhiteSpace(Guid)) return;

            var re = new RegistryEditor();

            re.RemoveKey(BaseKey, Guid);

            RemoveServiceCacheKey("15.0", Guid); //Office 2013
            RemoveServiceCacheKey("16.0", Guid); //Office 2016
        }


        public static void RemoveServiceCacheKey(string officeVersion, string guid)
        {
            var key = string.Format(ServicesManagerCachePath, officeVersion);
            var re = new RegistryEditor();
            var serviceKeyName = "OFFOPTIN_DOCSTORAGE_LIMITED_" + guid;

            if (re.GetKey(key) != null)
            {
                var identitiesKey = key + "\\Identities";
                var servicesCatalogKey = key + "\\ServicesCatalog";

                if(re.GetKey(identitiesKey) != null)
                {
                    var subkeys = re.GetSubKeyNames(identitiesKey);
                    foreach(var k in subkeys)
                    {
                        var keyName = $"{identitiesKey}\\{k}";
                        var subKeyName = re.GetSubKeyNames(keyName).Where(s => s.StartsWith(serviceKeyName)).FirstOrDefault();

                        if (!string.IsNullOrWhiteSpace(subKeyName))
                            re.RemoveKey(keyName, subKeyName);
                    }
                }

                if(re.GetKey(servicesCatalogKey) != null)
                {
                    re.RemoveKey(servicesCatalogKey, serviceKeyName);
                }
            }
        }

        public override string ToString()
        {
            return DisplayName;
        }
    }
}
